package com.have.blog.admin.annotion.avoidRepeatableCommit;


import com.have.blog.base.holder.RequestHolder;
import com.have.blog.commons.service.RedisService;
import com.have.blog.utils.IpUtils;
import com.have.blog.utils.MyStringUtils;
import com.have.blog.utils.ResultUtils;
import com.have.blog.xo.constant.RedisConstant;
import com.have.blog.xo.constant.SysConstant;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
@Slf4j
public class AvoidRepeatableCommitAspact {
    @Autowired
    private RedisService redisService;
    @Value("${redis.admin.database}")
    private String REDIS_KEY_DATABASE;

    @Around("@annotation(com.have.blog.admin.annotion.avoidRepeatableCommit.AvoidRepeatableCommit)")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        HttpServletRequest request = RequestHolder.getRequest();
        String ip = IpUtils.getIpAddr(request);

        // 获取注解
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();

        // 目标类方法
        String className = method.getDeclaringClass().getName();
        String methodName = method.getName();
        // 得到类名方法
        String formatClassNameMethodName = String.format("%s#%s", className, method);
        int hashCode = Math.abs(formatClassNameMethodName.hashCode());
        String key = String.format("%s:%s:%s_%d",
                REDIS_KEY_DATABASE,
                RedisConstant.AVOID_REPEATABLE_COMMIT,
                ip,
                hashCode);
        log.info("classMethodKey={}, hashCode={}, key={}", formatClassNameMethodName, hashCode, key);
        AvoidRepeatableCommit annotation = method.getAnnotation(AvoidRepeatableCommit.class);
        long timeout = annotation.timeout();
        String value = (String) redisService.get(key);
        if (MyStringUtils.isNotBlank(value)) {
            log.info("请勿重复提交表单");
            return ResultUtils.result(SysConstant.ERROR, "请勿重复提交表单");
        }

        redisService.set(key, MyStringUtils.getUUID(), timeout, TimeUnit.MILLISECONDS);
        Object proceed = point.proceed();
        return proceed;
    }
}
